import 'dart:io';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:spendbook/common/constants.dart';

abstract class HttpException extends Exception {
  factory HttpException([String? message, int? code]) => _HttpException(message, code);
}

class _HttpException implements HttpException {
  _HttpException([this.message, this.code]);

  String? message;

  int? code;

  @override
  String toString() {
    return message ?? '' + '-' + code.toString();
  }
}

class Http {
  static Future<Map<String, String>> _getHeaders() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    Map<String, dynamic> _user = await JsonDecoder().convert(prefs.getString('user') ?? '{}');

    return <String, String>{'Content-Type': 'application/json', 'platform': Platform.isIOS ? 'ios' : 'android', 'uid': _user['id'].toString()};
  }

  static Future<String> _getBaseUrl() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    return await prefs.getString('server') ?? '';
  }

  Future httpPost(String url, Object data) async {
    final baseApiUrl = await _getBaseUrl();
    http.Response response = await http.post(Uri.parse(baseApiUrl + url), body: JsonEncoder().convert(data), headers: await _getHeaders());
    return await _checkResponse(response);
  }

  Future httpGet(String url) async {
    final baseApiUrl = await _getBaseUrl();
    http.Response response = await http.get(Uri.parse(baseApiUrl + url), headers: await _getHeaders());
    return await _checkResponse(response);
  }

  Future httpPut(String url, Object data) async {
    final baseApiUrl = await _getBaseUrl();
    http.Response response = await http.put(Uri.parse(baseApiUrl + url), body: JsonEncoder().convert(data), headers: await _getHeaders());
    return await _checkResponse(response);
  }

  Future httpDelete(String url) async {
    final baseApiUrl = await _getBaseUrl();
    http.Response response = await http.delete(Uri.parse(baseApiUrl + url), headers: await _getHeaders());
    return await _checkResponse(response);
  }

  Future _checkResponse(http.Response response) async {
    if (response.statusCode != 200) {
      throw new HttpException(response.reasonPhrase, response.statusCode);
    }
    final data = await jsonDecode(utf8.decode(response.bodyBytes));
    if (data is Map && data.containsKey('error')) {
      print(data);
      return {};
    }
    return data;
  }
}
